#include "Motor.h"

MotorState_t eMotorState = MotorSt_Stop;
enum {run = 0,stop}eMotorRunStopState;
MotorRunState_t xMotorMode = {0};

static void MotorRunStopControlProcess(void);

void MotorAppProcess(void)
{
    MotorRunStopControlProcess();
}

void MotorInit(void)
{
    xMotorMode.dir = 0;//电机运行方向 0:顺时针 1:逆时针
}

static BldcPhase_t prvGetNextPhase(BldcPhase_t eCurrentPhase,uint16_t dir)
{
    BldcPhase_t eNextPhase;

    if(!(dir==0 || dir==1)){
        return PHASE_ERROR;
    }

    switch(dir)
    {
        case 0://顺时针
            if( eCurrentPhase ==  PHASE1 ){
                eNextPhase = PHASE6;
            }else{
                 eNextPhase = (BldcPhase_t)(eCurrentPhase - 1);
            }
            break;
        case 1://逆时针
            if( eCurrentPhase ==  PHASE6 ){
                eNextPhase = PHASE1;
            }else{
                 eNextPhase = (BldcPhase_t)(eCurrentPhase + 1);
            }
            break;    
        default:
            break;
    }
    
    return eNextPhase;
}

static void MotorRunStopControlProcess(void)
{
    uint16_t u16PotValue = u16SampleSwitchPotValue();
    if( eMotorRunStopState == stop )
    {
        if( u16PotValue>=200 ){
            eMotorRunStopState = run;
            eMotorState = MotorSt_Orient_1st_Init;
        }
    }
    else
    {
        if( u16PotValue<=180 ){
            eMotorRunStopState = stop;
            eMotorState = MotorSt_Stop;
        }        
    }
}

MotorState_t eMotorStateMachine(void)
{
    switch (eMotorState)
    {
        case MotorSt_Stop:
            xMotorMode.CCR = 0;
            BldcPwmControl(PHASE_ERROR);
            break;
        case MotorSt_Orient_1st_Init:
            xMotorMode.CCR = ORIENT_INIT_CCR;
            xBldcRunMode.ePhase = PHASE1;
            xTimeCounter.orientCounter = ORIENT_INIT_TIME;
            eMotorState = MotorSt_Orient_1st;
            break;
        case MotorSt_Orient_1st://转子一次预定位
            if( !xTimeCounter.orientCounter ){
                eMotorState = MotorSt_Orient_2nd_Init;
            }else{
                BldcPwmControl(xBldcRunMode.ePhase);
            }
            break;
        case MotorSt_Orient_2nd_Init:
            xMotorMode.CCR = ORIENT_INIT_CCR;
            xBldcRunMode.ePhase = prvGetNextPhase(xBldcRunMode.ePhase,xMotorMode.dir);
            xTimeCounter.orientCounter = ORIENT_INIT_TIME;
            eMotorState = MotorSt_Orient_2nd;
            break;
        case MotorSt_Orient_2nd://转子二次预定位
            if( !xTimeCounter.orientCounter ){
                eMotorState = MotorSt_Orient_End;
            }else{
                BldcPwmControl(xBldcRunMode.ePhase);
            }
            break;            
        case MotorSt_Orient_End://预定位结束，初始化升频升压
            /*设定初相位，这里调用一次，强拖换向时调用一次，达到连续调用两次获取相位函数，
              使得第一下升频升压的定子磁场领先转子磁场两个扇区(120度)*/
            xBldcRunMode.ePhase = prvGetNextPhase(xBldcRunMode.ePhase,xMotorMode.dir);
            /*设置退磁等待计数值*/
            xSensorlessInfo.deMagnezationCnt = DE_MAGENIZATION_TIME;
            /*设置强拖最小占空比*/
            xMotorMode.CCR = FORCE_RUN_CCR_MIN;
            /*设置换向导通时间基准，重置换向导通时间计数器*/
            xSensorlessInfo.ForceRunPhaseTimeBase = FORCE_RUN_PHASE_TIME_MAX;
            xSensorlessInfo.ForceRunPhaseTimeCnt = 0;
            /*设定退出强拖进入无感的条件：端电压检测到反电动势最大值*/
            xSensorlessInfo.ForceRunOutTerminalVoltage = 2708;
            /*状态跳转至强拖(升频升压)状态*/
            eMotorState = MotorSt_Force_Run;
            xForceRunState = PhaseSwitch;
            break;
        case MotorSt_Force_Run:
        {
            xSensorlessInfo.deMagnezationCnt--;
            switch(xForceRunState)//强拖状态机
            {
                case PhaseSwitch:
                    xBldcRunMode.ePhase = prvGetNextPhase(xBldcRunMode.ePhase,xMotorMode.dir);
                    BldcPwmControl(xBldcRunMode.ePhase);
                    xSensorlessInfo.deMagnezationCnt = DE_MAGENIZATION_TIME;
                    xSensorlessInfo.ForceRunPhaseTimeCnt = 0;
                    xForceRunState = ZPointDetect;
                    break;
                case DEventDelay:
                    if( !xSensorlessInfo.deMagnezationCnt ){
                        xForceRunState = ZPointDetect;
                    }
                    break;
                case ZPointDetect:
                    /*检测过零点切无感*/

                    /*检测是否升频升压*/
                    if( xSensorlessInfo.ForceRunPhaseTimeCnt >= xSensorlessInfo.ForceRunPhaseTimeBase ){
                        xForceRunState = FVIncrement;//长时间没检测到过零点,升频升压后换向
                    }
                    break;
                case FVIncrement:
                    /*升压(占空比)*/
                    xMotorMode.CCR += FORCE_RUN_CCR_STEP;
                    if( xMotorMode.CCR >= FORCE_RUN_CCR_MAX ){
                        xMotorMode.CCR = FORCE_RUN_CCR_MAX;
                    }
                    /*升频*/
                    xSensorlessInfo.ForceRunPhaseTimeBase -= FORCE_RUN_PHASE_TIME_STEP;
                    if( xSensorlessInfo.ForceRunPhaseTimeBase <= FORCE_RUN_PHASE_TIME_MIN ){
                        xSensorlessInfo.ForceRunPhaseTimeBase = FORCE_RUN_PHASE_TIME_MIN;
                    }
                    xForceRunState = PhaseSwitch;
                    break;
                case SensorlessStart:
                    break;                        
                default:
                    BldcOff();
                    break;
            }
            break;
        }
        case MotorSt_Sensorless_Run:
            break;
        default:
            break;
    }
	return eMotorState;
}

MotorState_t eGetMotorState(void)
{
    return eMotorState;
}
